package p2psvideo;

import android.app.UiModeManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import p2pproxy.FileTimeInfo;
import p2psvideo.Interfaces.OnSeekCompleteListener;
import p2psvideo.Interfaces.OnVideoSizeChangedListener;

public class P2PSPlayer extends FrameLayout {
	///控制条接口
	public interface IController
	{
		//挂接播放器
		public void attachPlayer(P2PSPlayer player);
		//取消与播放器的挂接
		public void detachPlayer();
		//显示控制条
		public void showController();
		//隐藏控制条
		public void hideController();
		//播放状态发生改变
		public void statusChanged();
		/*!
		 * @breif 更新播放位置
		 * @param position 当前播放点(ms)
		 * @param duration 总时长(ms)
		 */
		public void updatePosition(int position, int duration);
		//播放源源发生变化是触发调用
		public void playSourceChanged();
	}
	private boolean _hasHardAVC;
	private SurfaceHolder _holder;
	private SurfaceView _sf;
	private MediaPlayer _player;
	private IP2PSRemote _dataProvider;
	///标记是否需要恢复到记录的位置进行播放
	private boolean _needSeekToOldPos = false;
	private int _currentPos = 0;
	private int _oldPos = 0;
	private int _lastCheckPos = -2; //用于检测播放头是否不在走动
	private int _samePosCount = 0;
	private boolean _playing = false;
	private boolean _lastLoading = false;
	private boolean _ended = false;
	private boolean _everReady = false;
	private boolean _usingRaw = false;
	private int _activePlayerCount=0;
	private Handler _handler;
	private Interfaces.OnCompletionListener _onComplete;
	final static int msgRestart=1000;
	final static int msgHideStatus=1001;
	final static int msgTimer=1002;
	final static int msgInvalidateDebugKey=1003;
	private TextView _debugText;
	private TextView _statusText;
	private ServiceConnection _svcConn;
	private boolean _enableDebugMsg = false;
	private boolean _enableDebugKey = false;
	private int _debugKeyCount = 0;
	private boolean _debugKeyStateDown = false;

	private boolean _pausing = false;
	private boolean _seeking = false;
	private boolean _preparing = false;
	private boolean _rawBufferFinish = false;
	private boolean _showingStatus = false;
	private boolean _timeShift = false;
	private boolean _recoverFromCrash = false;
	private String _lastErrMsg = "";
	private SimpleDateFormat _sdf = new SimpleDateFormat("HH:mm:ss");
	///标识surface是否OK
	private boolean _surfaceOK = false;
	private Interfaces.OnErrorListener _onPlayError = null;
	///播放条目
	class PlayItem {
		public String url;
		public int start;
		public int duration;
		public int type;
		public String streamer;
		public String opts;
		public PlayItem(String url, String streamer, String opts, int start, int duration, int type)
		{
			this.url = url;
			this.start = start;
			this.duration = duration;
			this.type = type;
			this.streamer = streamer;
			this.opts = opts;
		}
	}

	private List<PlayItem> _items = new ArrayList<PlayItem>();
	private CharSequence _lastErrorMsg;
	private boolean _errorFired;

	//加载中控件
	protected View _loadingView;
	//暂停视图
	protected View _pausingView;
	//控制条控件
	protected View _controllerView;

	public P2PSPlayer(Context context) {
		super(context);
		init();
	}

	public P2PSPlayer(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	///获取数据传输内核返回的调试文本
	public String getStatus()
	{
		try {
			if (_dataProvider != null) {
				return _dataProvider.getStatus();
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	///是否无信号, 进当直播时有效
	public boolean noSignal()
	{
		try {
			if (_dataProvider != null) {
				return _dataProvider.noSignal();
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	///控制播放器使用ts方式还是m3u8方式播放
	public boolean useTS = false;
	///是否采用填充空TS帧方式保持播放器连接（某些信号的机顶盒可能需要此选项，否则可能出现播放卡顿）
	public boolean usePadding = false;
	///是否采用传输数据缓冲区空来检查点播结束
	public boolean bufferEmptyToEnd = false;
	///是否采用旧模式播放
	public boolean traditionalMode = false;

	/*!
	 * @brief 是否处理键盘事件
	 * @note 如果处理键盘事件开启时，按键盘的DPAD_CENTER和ENTER键将在暂停和恢复播放中切换；在开启键盘事件时，播放器的onKeyDown事件将会传导至控制条视图的onKeyDown
	 */
	public boolean handleKey = false;
	private GestureDetector _gesture;
	private Interfaces.OnPreparedListener _onPrepared;
	private boolean _onPreparedCalled = false;
	private OnSeekCompleteListener _onSeekComplete;
	private boolean _onSeekCompleteCalled = true;
	private OnVideoSizeChangedListener _onVideoSizeChanged;
	private Interfaces.OnBufferingUpdateListener _onBufferingUpdate;
	///显示比例
	private double _aspectRatio;
	///视频宽度
	private int _videoWidth;
	///视频高度
	private int _videoHeight;
	///解码器列表
	private String _codecList;

	/*!
	 * @brief 添加文件
	 * @param urls 要播放的视频的地址, 如果是VMS流，请传入.json的URL
	 * @param streamers 串流服务器的地址，通常是rtmfp://协议的地址
	 * @param opts 播放选项，JSON格式, 目前支持的选项包括:
	 * 		buffer_length: 视频播放缓冲区长度，单位ms, 典型的设置为30000
	 * 		referer: 视频的引用页，当服务器开启了防盗链时需要传递此参数
	 * 		video_codecs: 设备支持的视频解码器列表
	 * @param start 视频片段的开始点（ms)，如果不希望视频被截断，设置为0
	 * @param duration 视频片段的结束点 (ms). 如果不希望视频被截断，设置为-1
	 * @param index 文件位置，加到尾部则设置为-1
	 * @param type 视频格式， 目前请设置为0, 由播放器自动识别
	 */
	public boolean addFile(String urls, String streamers, String opts, int start, int duration, int index, int type)
	{
		if (index != -1 && index < 0 || index > _items.size()) { //out of range
			return false;
		}
		PlayItem it = new PlayItem(urls, streamers, opts, start, duration, type);
		if (index == -1) {
			_items.add(it);
		} else {
			_items.add(index, it);
		}
		if (_dataProvider != null) {
			try {
				_dataProvider.addFile(urls, streamers, opts, start, duration, index, type);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		if (_controllerView != null) {
			((IController)_controllerView).playSourceChanged();
		}
		return true;
	}

	///获取文件数量
	public int fileCount()
	{
		return _items.size();
	}

	///清除所有文件
	public void clear()
	{
		_items.clear();
		if (_dataProvider != null) {
			try {
				_dataProvider.clear();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		if (_controllerView != null) {
			((IController)_controllerView).playSourceChanged();
		}
	}
	///移除某个文件
	public boolean removeFile(int index)
	{
		if (index < 0 || index >= _items.size()) return false;
		_items.remove(index);
		if (_dataProvider != null) {
			try {
				_dataProvider.removeFile(index);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		if (_controllerView != null) {
			((IController)_controllerView).playSourceChanged();
		}
		return true;
	}
	///判断文件是否已经加载完毕
	public boolean fileReady(int index)
	{
		if (index < 0 || index >= _items.size()) return false;
		if (_dataProvider != null) {
			try {
				return _dataProvider.fileReady(index);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	///判定底层数据传输组件是否已经创建
	public boolean dataProviderCreated()
	{
		return _dataProvider != null;
	}

	///获取服务接口
	public IP2PSRemote getService()
	{
		return _dataProvider;
	}

	///设置播放错误接口
	public void setOnPlayError(Interfaces.OnErrorListener cb)
	{
		_onPlayError = cb;
	}

	///设置文件加载成功回调
	public void setOnPreparedListener(Interfaces.OnPreparedListener l)
	{
		_onPrepared = l;
	}

	///设置播放文件回调
	public void setOnCompletionListener(Interfaces.OnCompletionListener l)
	{
		_onComplete = l;
	}

	///设置定位完成回调
	public void setOnSeekCompleteListener(OnSeekCompleteListener l)
	{
		_onSeekComplete = l;
	}

	///设置视频大小发生变化回调
	public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener l)
	{
		_onVideoSizeChanged = l;
	}

	///设置缓冲百分比变化回调
	public void setOnBufferingUpdateListener(Interfaces.OnBufferingUpdateListener l)
	{
		_onBufferingUpdate = l;
	}

	///获取是否直播
	public boolean isLive()
	{
		if (!dataProviderCreated()) return false;
		try {
			return _dataProvider.isLive();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		return false;
	}

	/*!
	 * @brief 获取是否处于时移模式
	 * @note 直播处于时移模式时暂停操作在一定时间内（取决于视频流的可时移长度设置）不会丢失视频内容，在非时移模式时的直播如果暂停一段时间再恢复播放会丢失暂停时间内的视频数据，直接跳到实时点进行播放.
	 */
	public boolean inTimeShiftMode() {
		if (!dataProviderCreated())
			return false;
		try {
			return _dataProvider.inTimeShiftMode() == 1;
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		return false;
	}

	/*!
	 * @brief 获取有时移模式
	 * @return 当前直播是否可以时移
	 * @note 时移模式是指直播流可以进行回退，暂停，前进操作而在一定时间内（取决于视频流的可时移长度设置）不会丢失视频内容
	 */
	public boolean hasTimeShiftMode() {
		if (!dataProviderCreated())
			return false;
		try {
			return _dataProvider.inTimeShiftMode() != 0;
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		return false;
	}

	///暂停播放
	public void pause()
	{
		_lastErrMsg = "";
		_playing = false;
		_pausing = true;
		showStatusText();
		if (_controllerView != null) {
			((IController)_controllerView).statusChanged();
		}
		if (_pausingView != null) {
			_pausingView.setVisibility(VISIBLE);
			_pausingView.requestLayout();
		}
		if (_usingRaw) {
			if (_dataProvider != null) {
				try {
					_dataProvider.pause();
				} catch (RemoteException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return;
		}
		if (_player == null) return;
		if (_preparing) return;

		try {
			_player.pause();
			try {
				_dataProvider.pause();
			} catch (RemoteException e) {
				e.printStackTrace();
				_lastErrMsg = e.getMessage();
			}
		} catch( IllegalStateException e) {
			_lastErrMsg = e.getMessage();
		}
	}

	/*!
	 * @brief 恢复播放
	 * @note 如果视频尚未加载则执行加载操作，如果视频已经加载并处于暂停中则执行续播操作
	 */
	public void resume()
	{
		_lastErrMsg = "";
		_playing = true;
		_pausing = false;
		showStatusText();
		if (_controllerView != null) {
			((IController)_controllerView).statusChanged();
		}
		if (_pausingView != null) {
			_pausingView.setVisibility(INVISIBLE);
		}
		if (_dataProvider == null) {
			recreateDataProvider();
			return;
		}
		if (_usingRaw) {
			if (_dataProvider != null) {
				try {
					_dataProvider.play();
				} catch (RemoteException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			return;
		}
		if (_preparing) return;
		if (_player == null) return;
		try {
			if (!_dataProvider.ready()) { //数据尚未准备好
				return;
			}
			_player.start();
			_dataProvider.play();
		} catch( Exception e) {
			_lastErrMsg = e.getMessage();
			e.printStackTrace();
		}
	}

	/*!
	 * @brief 判断视频是否已经加载完毕
	 * @return 是否加载完毕
	 */
	public boolean ready()
	{
		if (_player == null && !_usingRaw) return false;
		if (_dataProvider == null) return false;
		try {
			if (!_dataProvider.ready()) { //数据尚未准备好
				return false;
			}
		} catch (RemoteException e) {
			e.printStackTrace();
			return false;
		}
		if (_usingRaw) {
			return _rawBufferFinish;
		}
		return !_preparing;
	}

	/*!
	 * @brief 执行定位操作
	 * @param t 定位时间点, 单位ms
	 * @note 必须在视频加载完毕后发出，否则无效
	 */
	public void seek(int t)
	{
		_pausing = false;
		innerSeek(t, 0, false, false, false);
	}

	/*!
	 * @brief 执行定位操作, 精确到关键帧
	 * @param t 定位时间点, 单位ms
	 * @note 必须在视频加载完毕后发出，否则无效
	 */
	public void seekToKeyFrame(int t)
	{
		_pausing = false;
		innerSeek(t, 0, true, false, false);
	}

	/*!
	@brief 定位到时间码
	@pparam tc 定位时间码，单位ms
	@param keyFrameAccuracy 精确到关键帧定位
	@param mustMatch 是否必须匹配到，如果设置为true则必须精确匹配才执行定位，否则放弃定位；如果设置为false则匹配最近的时间码进行定位
	@param asc 时间码扫描方式,true为从第一个文件开始扫描，false为从最后一个文件开始扫描
	 */
	public void seekByTimeCode(double tc, boolean keyFrameAccuracy, boolean mustMatch, boolean asc)
	{
		_pausing = false;
		innerSeek(0, tc, keyFrameAccuracy, mustMatch, asc);
	}

	/*!
	@brief 获取文件时间码信息
	 */
	public FileTimeInfo getFileTimeInfo(int idx)
	{
		if (!dataProviderCreated()) return null;
		try {
			return _dataProvider.getFileTimeInfo(idx);
		} catch (RemoteException e) {
			e.printStackTrace();
			return null;
		}
	}

	///定位
	private void innerSeek(int t, double tc, boolean keyFrameAccuracy, boolean mustMatch, boolean asc)
	{
		Log.v("P2PSPlayer", "seek: "+t);
		_lastErrMsg = "";
		if (!dataProviderCreated()) return;
		if (!_usingRaw) closePlayer();
		_ended = false;
		_playing = true;
		_pausing = false;
		_needSeekToOldPos = false;
		_oldPos = t;
		_onSeekCompleteCalled = false;
		if (_controllerView != null) {
			((IController)_controllerView).statusChanged();
		}
		if (_pausingView != null) {
			_pausingView.setVisibility(INVISIBLE);
		}
		try {
			if (tc != 0) {
				if (!_dataProvider.seekByTimeCode(tc, keyFrameAccuracy, mustMatch, asc)) {
					return;
				}
				_rawBufferFinish = false;
			} else if (keyFrameAccuracy) {
				if (!_dataProvider.seekToKeyFrame(t)) {
					return;
				}
				_rawBufferFinish = false;
			} else {
				if (!_dataProvider.seek(t)) {
					return;
				}
				_rawBufferFinish = false;
			}
			if (!_usingRaw) _dataProvider.play();
		} catch(Exception e) {
			e.printStackTrace();
			return;
		}
		try {
			if (!_usingRaw) {
				closePlayer();
				createPlayer();
			}
			showStatusText();
		} catch(Exception e) {
			_lastErrMsg = e.getMessage();
			e.printStackTrace();
		}
	}


	/*!
	 * @brief 获取播放总长度, 如果有直播条目，则播放总长度会发生变化
	 * @return 视频时长，单位ms
	 */
	public int duration()
	{
		if (!dataProviderCreated()) {
			return 0;
		}
		try {
			return _dataProvider.duration();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		return 0;
	}

	/*!
	 * @brief 获取当前播放器播放内容的时间码,单位为ms
	 * @return 以毫秒为单位的时间码
	 * @note 这个函数要求视频流中包含时间码信息，否则一律返回0. 时间码是编码在视频流中的从1970.1.1开始的绝对时间戳。
	 */
	public double getTimeCode()
	{
		if (!dataProviderCreated()) return 0;
		if (_usingRaw) {
			int ct;
			try {
				ct = _dataProvider.getRawTime();
				if (ct == -1) return 0;
				return _dataProvider.getOutSidePlayerTimeCode(ct);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return 0;
		}
		if (_player == null || _preparing) return 0;
		int ct = _player.getCurrentPosition();
		try {
			return _dataProvider.getOutSidePlayerTimeCode(ct);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;
	}

	private int currentPositionInner()
	{
		if (!dataProviderCreated()) return -1;
		if (_usingRaw) {
			int r;
			try {
				r = _dataProvider.getRawTime();
				if (r == -1) return -1;
				if (r < 0) r = 0;
				return _dataProvider.getOutSidePlayerStreamTime(r);
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return -1;
		}
		if (_player == null || _preparing)
			return -1;
		try {
			int r=0;
			try {
				r = _player.getCurrentPosition();
			} catch (Throwable e) {
				;
			}
			if (r < 0) r = 0;
			return _dataProvider.getOutSidePlayerStreamTime(r);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}

	///获取当前播放点, 返回毫秒为单位的播放进度
	public int currentPosition()
	{
		int r = currentPositionInner();
		if (r == -1) return 0;
		else return r;
	}

	///返回是否处于播放状态
	public boolean playing()
	{
		if (_dataProvider == null) return false;
		if (_player == null && !_usingRaw) return false;
		if (!_playing) return false;
		if (_usingRaw) {
			try {
				return !_dataProvider.rawBufferring();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return _playing;
	}

	///返回是否处于暂停状态
	public boolean pausing()
	{
		//if (_dataProvider == null) return false;
		//if (_player == null) return false;
		return _pausing;
	}

	/*!
	 * @brief 是否启用状态文本
	 * @note 状态文本在左上角，绿色，显示当前播放器状态和进度
	 */
	public void enableStatusText(boolean v)
	{
		if (v) {
			_statusText.setVisibility(VISIBLE);
		} else {
			_statusText.setVisibility(INVISIBLE);
		}
		updateStatusText();
	}

	///是否启用调试文本
	public void enableDebugText(boolean v)
	{
		if (v != _enableDebugMsg && v) {
			LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
			_debugText.setLayoutParams(lp);
		}
		_enableDebugMsg = v;
		if (v) {
			_debugText.setVisibility(VISIBLE);
		} else {
			_debugText.setVisibility(INVISIBLE);
		}
	}

	///是否启用音量+-特殊键调取出调试信息
	public void enableDebugKey(boolean v)
	{
		_enableDebugKey = v;
	}

	///停止播放并释放资源
	public void stop() {
		if (_player != null) {
			Log.v("P2PSPlayer", "Stop current player: " + _player.hashCode() + ", playercount=" + _activePlayerCount);
		} else {
			Log.v("P2PSPlayer", "Stop no player");
		}
		closeService();
		_playing = false;
		_preparing = false;
		_seeking = false;
		_pausing = false;
		_needSeekToOldPos = false;
		_currentPos = 0;
		_oldPos = 0;
		_videoWidth = 0;
		_videoHeight = 0;
		_everReady = false;
		_onPreparedCalled = false;
		_onSeekCompleteCalled = true;
		_lastLoading = false;
		_handler.removeCallbacksAndMessages(null);
		if (_controllerView != null) {
			((IController)_controllerView).statusChanged();
		}
		if (_pausingView != null) {
			_pausingView.setVisibility(INVISIBLE);
		}
		if (_loadingView != null) {
			_loadingView.setVisibility(INVISIBLE);
		}
	}

	public void clearScreen()
	{
		LayoutParams l1 = (LayoutParams)_sf.getLayoutParams();
		this.removeView(_sf);
		this.addView(_sf, 0);
		_sf.setLayoutParams(l1);
		_holder = _sf.getHolder();
	}
	///获取当前播放的文件信息
	public P2PSMgr.P2PSFileInfo getCurrentFileInfo()
	{
		if (_dataProvider == null) {
			Log.e("P2PSService", "Service is not init");
			return null;
		}
		try {
			return P2PSMgr.getFileInfo(_dataProvider, _dataProvider.getCurrentPlayVsid());
		} catch(Throwable e) {
			e.printStackTrace();
		}
		return null;
	}

	///是否播放结束
	public boolean ended()
	{
		return _ended;
	}

	///释放播放器
	public void release() {
		stop();
	}

	/*!
	 * @brief 设置加载中视图
	 * @param v 加载中视图, 如果为null则取消加载中视图
	 * @param width 宽度，如果为0则使用v本身的内容宽度
	 * @param height 高度， 如果为0则使用v本身的内容高度
	 */
	public void setLoadingView(View v, int width, int height)
	{
		if (v == _loadingView) return;
		if (_loadingView != null) this.removeView(_loadingView);
		_loadingView = v;
		if (v == null) return;
		if (width == 0) width = LayoutParams.WRAP_CONTENT;
		if (height == 0) height = LayoutParams.WRAP_CONTENT;
		LayoutParams l = new LayoutParams(width, height);
		l.gravity = Gravity.CENTER;
		this.addView(v);
		v.setLayoutParams(l);
		v.requestLayout();
	}

	/*!
	 * @brief 设置暂停视图
	 * @param v 暂停视图, 如果为null则取消暂停视图
	 * @param width 宽度，如果为0则使用v本身的内容宽度
	 * @param height 高度， 如果为0则使用v本身的内容高度
	 */
	public void setPausingView(View v, int width, int height)
	{
		if (v == _pausingView) return;
		if (_pausingView != null) this.removeView(_pausingView);
		_pausingView = v;
		if (v == null) return;
		if (width == 0) width = LayoutParams.WRAP_CONTENT;
		if (height == 0) height = LayoutParams.WRAP_CONTENT;
		LayoutParams l = new LayoutParams(width, height);
		l.gravity = Gravity.CENTER;
		this.addView(v);
		v.setLayoutParams(l);
		v.requestLayout();
		if (_pausing) {
			_pausingView.setVisibility(VISIBLE);
		} else {
			_pausingView.setVisibility(INVISIBLE);
		}
	}

	/*!
	 * @brief 设置控制条视图
	 * @param v 控制条视图, 必须实现IController接口
	 * @param width 视图宽度
	 * @param height 视图高度
	 * @param margin 距离上或者下的边距
	 * @param bottom 控制条是否放置在下面
	 */
	public void setControllerView(View v, int width, int height, int margin, boolean bottom)
	{
		if (v == _controllerView) return;
		if (_controllerView != null) {
			((IController)_controllerView).detachPlayer();
			this.removeView(_controllerView);
			_controllerView = null;
		}
		if (!(v instanceof IController)) {
			return;
		}
		_controllerView = v;
		if (width == 0) width = LayoutParams.WRAP_CONTENT;
		if (height == 0) height = LayoutParams.WRAP_CONTENT;
		LayoutParams l = new LayoutParams(width, height);
		if (bottom) {
			l.gravity = Gravity.BOTTOM|Gravity.CENTER;
			l.bottomMargin = margin;
		} else {
			l.gravity = Gravity.TOP|Gravity.CENTER;
			l.topMargin = margin;
		}
		this.addView(v);
		v.setLayoutParams(l);
		v.setVisibility(VISIBLE);
		v.requestLayout();
		((IController)v).attachPlayer(this);
	}

    /**
     * 设置控制器
     * @param v
     */
	public void setControllerView(View v)
	{
		if (v == _controllerView) return;
		if (_controllerView != null) {
			((IController)_controllerView).detachPlayer();
			//this.removeView(_controllerView);
			_controllerView = null;
		}
		if (!(v instanceof IController)) {
			return;
		}
		_controllerView = v;
		((IController)v).attachPlayer(this);
	}


	//控制条显示或隐藏
	public void showController(boolean v)
	{
		if (_controllerView != null) {
			IController c = (IController)_controllerView;
			if (v) {
				c.showController();
			} else {
				c.hideController();
			}
		}
	}

	///获取播放器的SurfaceView
	public SurfaceView getSurfaceView()
	{
		return _sf;
	}

	///设置视频显示比例 0 为满屏, -1 为原始比例
	public void setDisplayAspectRatio(double aspectRatio)
	{
		if (_aspectRatio != aspectRatio) {
			_aspectRatio = aspectRatio;
			_updateAspect(-1, -1);
		}
	}

	///获取当前设置的显示比例
	public double getDisplayAspectRatio()
	{
		return _aspectRatio;
	}

	///获取视频的宽度, 当onVideoSizeChanged事件触发后有效
	public int getVideoWidth()
	{
		return _videoWidth;
	}

	///获取视频的高度，当onVideoSizeChanged事件触发后有效
	public int getVideoHeight()
	{
		return _videoHeight;
	}

	private void _updateAspect(int w, int h)
	{
		if (_sf == null) return;
		if (w == -1) {
			w = this.getWidth();
			h = this.getHeight();
		}
		double r=_aspectRatio;
		if (w == 0 || h == 0) { //某些场合onSizeChanged丢失导致丢失了一次宽度和高度的检测，此时我们直接满屏，防止图像不显示
			r = 0;
		}
		if (r < 0) { //按视频原始比例
			if (_videoWidth == 0 || _videoHeight == 0) {
				r = 0;
			} else {
				r = (double)_videoWidth / (double)_videoHeight;
			}
		}
		if (r == 0) {
			LayoutParams l1 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
			_sf.setLayoutParams(l1);
			return;
		}
		//先按照宽度计算出高度
		int vw = w;
		int vh = h;
		if (w > r*h) { //屏幕比大于视频比，屏幕比例比视频比例扁， 以屏幕高度计算宽度
			vh = h;
			vw = (int)((double)h * r);
		} else { //以屏幕宽度计算高度
			vw = w;
			vh = (int)(w / r);
		}
		LayoutParams l1 = new LayoutParams(vw,vh);
		int marginY = (h - vh) / 2;
		if (marginY < 0) marginY = 0;
		int marginX = (w - vw) / 2;
		if (marginX < 0) marginX = 0;
		l1.setMargins(marginX, marginY, marginX, marginY);
		_sf.setLayoutParams(l1);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		_updateAspect(w, h);
		super.onSizeChanged(w, h, oldw, oldh);
	}

	///创建界面部件
	private void init() {
		try {
			_hasHardAVC = P2PSMediaPlayer.hasHardwareCodecForType("video/avc");
		} catch(Throwable e) {
			_hasHardAVC = false;
		}
		try {
			_codecList = P2PSMediaPlayer.getSupportedVideoCodecList(true);
		} catch(Throwable e) {
			_codecList="";
		}
		FrameLayout v = this;
		SurfaceView sf = new SurfaceView(v.getContext())
		{
			protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
				int width = getDefaultSize(0, widthMeasureSpec);
				int height = getDefaultSize(0, heightMeasureSpec);
				//height = width * 4 / 3;
				setMeasuredDimension(width, height);
			}
		};
		LayoutParams l1 = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
		v.addView(sf);
		sf.setLayoutParams(l1);
		_debugText = new TextView(v.getContext());
		_debugText.setVisibility(INVISIBLE);
		v.addView(_debugText);
		LayoutParams l2 = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		_debugText.setLayoutParams(l2);
		_debugText.setTextColor(Color.GREEN);
		//_debugText.setFocusable(false);
		_debugText.setGravity(Gravity.LEFT);
		_debugText.setTextSize(20);
		 _gesture = new GestureDetector(this.getContext(), new SimpleOnGestureListener(){
				@Override
				public boolean onScroll(MotionEvent e1, MotionEvent e2,
						float distanceX, float distanceY) {
					if (_debugText.getVisibility() == VISIBLE) {
						LayoutParams lp = (LayoutParams)_debugText.getLayoutParams();
						lp.topMargin += distanceY;
						_debugText.setLayoutParams(lp);
					}
					return true;
				}

	      });
		 _debugText.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (_gesture != null) {
					_gesture.onTouchEvent(event);
				}
				return false;
			}

		 });
		_statusText = new TextView(v.getContext());
		_statusText.setLayoutParams(l2);
		_statusText.setGravity(Gravity.LEFT);
		_statusText.setTextColor(Color.GREEN);
		_statusText.setTextSize(32);
		_statusText.setFocusable(false);
		v.addView(_statusText);
		_sf = sf;
		sf.setFocusable(false);
		_holder = sf.getHolder();
		_holder.addCallback(new Callback() {

			@Override
			public void surfaceChanged(SurfaceHolder holder, int format,
					int width, int height) {
				Log.v("P2PSPlayer","surface surfaceChanged");
			}

			@Override
			public void surfaceCreated(SurfaceHolder holder) {
				Log.v("P2PSPlayer","surface surfaceCreated");
				_surfaceOK = true;
				createPlayer();
			}

			@Override
			public void surfaceDestroyed(SurfaceHolder holder) {
				Log.v("P2PSPlayer","surface surfaceDestroyed");
				_surfaceOK = false;
				if (pausing()) {
					if (!_needSeekToOldPos) {
						_needSeekToOldPos = true;
						_oldPos = _currentPos;
						Log.v("P2PSPlayer", "pausing to set oldPos:" +_oldPos);
					}else {
						_oldPos = _currentPos;
						Log.v("P2PSPlayer", "pausing to set oldPos:" +_oldPos);
					}
				}
				closePlayer();
			}

		});
		_holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		_player = null;
		_handler = new Handler() {
			public void handleMessage(Message msg) {
				switch(msg.what) {
				case msgHideStatus:
					_showingStatus = false;
					updateStatusText();
					break;
				case msgTimer:
					onTimer();
					_handler.sendEmptyMessageDelayed(msgTimer, 100);
					break;
				case msgRestart:
					closePlayer();
					resume();
					break;
				case msgInvalidateDebugKey:
					_debugKeyCount = 0;
					_debugKeyStateDown = false;
					break;
				}
			}
		};
		//启动服务
		try {
			Intent startIntent = new Intent(getContext(), P2PSService.class);
			getContext().startService(startIntent);
		} catch(Exception e) {
			e.printStackTrace();
		}
	}

	///定时器
	private void onTimer()
	{
		if (_enableDebugMsg) {
			String t = _lastErrorMsg+"\n";
			if (_usingRaw) {
				t += "RawBufferLength: ";
				if (_dataProvider != null)
					try {
						t += _dataProvider.getRawBufferLength()/1000;
					} catch (RemoteException e) {
						e.printStackTrace();
					}
				else t += "0";
				t += "\n";
			}
			t += this.getStatus();
		  _debugText.setText(t);
		}
		if (ready()) {
			int cp = currentPositionInner();
			if (cp != -1) {
				_currentPos = cp;
			}
			if (_controllerView != null && !_pausing) {
				((IController)_controllerView).updatePosition(_currentPos, duration());
			}
			//标记是否在崩溃时恢复到之前的播放位置
			if (_dataProvider != null) {
				try {
					if (!_dataProvider.isLive() || _dataProvider.inTimeShiftMode() == 1) {
						_needSeekToOldPos = true;
					} else {
						_needSeekToOldPos = false;
					}
				} catch (RemoteException e) {
					e.printStackTrace();
				}
			}
			if (!_onPreparedCalled) {
				_onPreparedCalled = true;
				if (_controllerView != null) {
					((IController)_controllerView).statusChanged();
				}
				if (_onPrepared != null) {
					_onPrepared.onPrepared();
				}
			}
			if (!_onSeekCompleteCalled) {
				_onSeekCompleteCalled = true;
				if (_controllerView != null) {
					((IController)_controllerView).statusChanged();
				}
				if (_onSeekComplete != null) {
					_onSeekComplete.onSeekComplete();
				}
			}
		}
		if (!_usingRaw) createPlayer();
		try {
			checkEOF();
		} catch(Exception e) {
			e.printStackTrace();
		}
		checkError();
		updateStatusText();
	}

	private void checkError()
	{
		if (_dataProvider == null || _errorFired) return;
		try {
			if (_dataProvider.error()) {
				_errorFired = true;
				closeService();
				callError(new Exception(), null);
				if (_controllerView != null) {
					((IController)_controllerView).statusChanged();
				}
			}
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	private void checkEOF()
	{
		if (_dataProvider == null) return;
		if (!_playing) return;
		if (_pausing || _preparing) return;
		if (_usingRaw) {
			try {
				if (_dataProvider.isEof()) {
					_playing = false;
					_ended = true;
					if (_onComplete != null) {
						_onComplete.onCompletion();
					}
					if (_controllerView != null) {
						((IController)_controllerView).statusChanged();
					}
				}
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			return;
		}
		try {
			if (_dataProvider.stopped()) {
				Log.v("P2PSPlayer", "data provider stop");
				if (_player.getCurrentPosition() == _lastCheckPos) {
					_samePosCount++;
					Log.v("P2PSPlayer", "data provider was stopped, same pos check: " + _samePosCount);
					if (_samePosCount > 30) {
						//播放结束
						_playing = false;
						_ended = true;
						try {
							_player.stop();
						} catch(Exception e) {
							e.printStackTrace();
						}
						if (_onComplete != null) {
							_onComplete.onCompletion();
						}
						if (_controllerView != null) {
							((IController)_controllerView).statusChanged();
						}
					}
				} else {
					_lastCheckPos = _player.getCurrentPosition();
					_samePosCount = 0;
					if (bufferEmptyToEnd && _dataProvider.bufferring()) {
						_playing = false;
						_ended = true;
						try {
							_player.stop();
						} catch(Exception e) {
							e.printStackTrace();
						}
						if (_onComplete != null) {
							_onComplete.onCompletion();
						}
						if (_controllerView != null) {
							((IController)_controllerView).statusChanged();
						}
					}
					Log.v("P2PSPlayer", "data provider was stopped, pos: " + _lastCheckPos);
				}
			} else {
				_lastCheckPos = -2;
				_samePosCount = 0;
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

	///当dataProvider初始化完毕后调用
	private void afterDataPrividerCreated()
	{
		_handler.removeMessages(msgTimer);
		_handler.sendEmptyMessage(msgTimer);
		_usingRaw = false;
		_rawBufferFinish = false;
		try {
			_dataProvider.setOnVideoSizeChangedListener(new p2psvideo.aidl.OnVideoSizeChangedListener.Stub() {
				@Override
				public void onVideoSizeChanged(final int width, final int height)
						throws RemoteException {
					_handler.post(new Runnable() {
						@Override
						public void run() {
							_videoWidth = width;
							_videoHeight = height;
							_updateAspect(-1, -1);
							if (_onVideoSizeChanged != null) {
								_onVideoSizeChanged.onVideoSizeChanged(width, height);
							}
						}
					});
				}
			});
		} catch (RemoteException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		try {
			_dataProvider.beginPlay(this.traditionalMode?"tsserver":null);
		} catch (RemoteException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		try {
			_usingRaw = _dataProvider.usingRaw();
		} catch (RemoteException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if (_usingRaw) {
			try {
				_dataProvider.setOnBufferingUpdateListener(new p2psvideo.aidl.OnBufferingUpdateListener.Stub() {
					@Override
					public void onBufferingUpdate(final int percent) throws RemoteException {
						_handler.post(new Runnable() {
							@Override
							public void run() {
								if (percent == 100) {
									_rawBufferFinish = true;
								}
								if (_onBufferingUpdate != null) {
									_onBufferingUpdate.onBufferingUpdate(percent);
								}
							}
						});
					}
				});
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		for(int i=0; i<_items.size(); ++i) {
			PlayItem it = (PlayItem)_items.get(i);
			try {
				_dataProvider.addFile(it.url, it.streamer, it.opts, it.start, it.duration, -1, it.type);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		if (_usingRaw) {
			_errorFired = false;
			createPlayer();
		}
		if (_playing) {
			try {
				_dataProvider.play();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (!_usingRaw) {
			_errorFired = false;
			createPlayer();
		}
	}

	///错误报告
	private void callError(Exception e, String msg)
	{
		if (_onPlayError != null) {
			_onPlayError.onError(e, msg);
		}
	}

	///关闭播放器和服务
	private void closeService()
	{
		closePlayer();
		if (_dataProvider != null) {
			try {
				_dataProvider.setOnVideoSizeChangedListener(null);
			} catch (RemoteException e1) {
				e1.printStackTrace();
			}
			try {
				_dataProvider.endPlay();
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		ServiceConnection c = _svcConn;
		_svcConn = null;
		_dataProvider = null;
		if (c != null) {
			try {
				getContext().unbindService(c);
			} catch(Exception e) {
				e.printStackTrace();
			}
		}
	}

	///重新创建服务
	private boolean recreateDataProvider()
	{
		closeService();
		//启动服务
		Intent startIntent = new Intent(getContext(), P2PSService.class);
		getContext().startService(startIntent);
		_svcConn = new ServiceConnection() {
			@Override
			public void onServiceConnected(ComponentName arg0, IBinder arg1) {
				_dataProvider = IP2PSRemote.Stub.asInterface(arg1);
				afterDataPrividerCreated();
			}

			@Override
			public void onServiceDisconnected(ComponentName arg0) {		//服务崩溃
				_oldPos = _currentPos;
				_recoverFromCrash = true;
				closeService();
				recreateDataProvider();
			}
		};
		try {
			Intent it = new Intent(getContext(), P2PSService.class);
			boolean r = getContext().bindService(it, _svcConn, Context.BIND_AUTO_CREATE);
			if (!r) {
				Log.e("P2PSService", "Bind to play failed");
			}
		} catch(Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	///关闭播放器
	private void closePlayer()
	{
		if (_usingRaw && dataProviderCreated()) {
			try {
				_dataProvider.setSurface(null);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
		if (_player != null && !_preparing) {
			if (_everReady) {
				try {
					_player.stop();
				} catch(Exception e) {
					e.printStackTrace();
				}
			}
			try {
				_player.setSurface(null);
			} catch(Throwable e) {
				e.printStackTrace();
			}
			try {
				_player.release();
			} catch(Exception e) {
				e.printStackTrace();
			}
			_activePlayerCount--;
		}
		_ended = false;
		_player = null;
		_preparing = false;
		_lastLoading = false;
		if (_controllerView != null) {
			((IController)_controllerView).statusChanged();
		}
		this.setKeepScreenOn(false);
	}

	///重新创建播放器
	private void createPlayer()
	{
		if (!_surfaceOK || !dataProviderCreated()) return;
		if (_usingRaw) {
			if (_recoverFromCrash) { //需要重构_sf
				_surfaceOK = false;
				_recoverFromCrash = false;
				LayoutParams l1 = (LayoutParams)_sf.getLayoutParams();
				this.removeView(_sf);
				this.addView(_sf, 0);
				_sf.setLayoutParams(l1);
				_holder = _sf.getHolder();
				return;
			}
			try {
				Surface surface = _sf.getHolder().getSurface();
				if (!surface.isValid()) {
					Log.v("P2PSService", "Surface for player is not valid");
				}
				_dataProvider.setSurface(surface);
				this.setKeepScreenOn(true);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			try {
				if (_needSeekToOldPos) {
					if (!_dataProvider.isLive()) {
						Log.v("P2PSPlayer", "Seek to old pos: " + _oldPos);
						_dataProvider.seek(_oldPos);

						Log.v("P2PSPlayer","Is Seek to old pause :" + pausing());
						if(pausing()){
							Log.v("P2PSPlayer", "Seek to old pos and pause");
							_dataProvider.pause();
						}
					}
					_needSeekToOldPos = false;
				} else {
					Log.v("P2PSPlayer", "No need to seek to old pos: " + _oldPos);
				}
			} catch (RemoteException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
				return;
			}
			return;
		}
		if (_player != null) return;
		showStatusText();
		if (!_playing) return;
		if (_preparing) return;
		try {
			if (!_dataProvider.ready()) {
				return;
			}
		} catch (RemoteException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return;
		}
		try {
			if (_needSeekToOldPos) {
				if (!_dataProvider.isLive()) {
					Log.v("P2PSPlayer", "Seek to old pos: " + _oldPos);
					_dataProvider.seek(_oldPos);
				}
				_needSeekToOldPos = false;
			} else {
				Log.v("P2PSPlayer", "No need to seek to old pos: " + _oldPos);
			}
		} catch (RemoteException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return;
		}
		_preparing = true;
		_activePlayerCount++;
		_player = new MediaPlayer();
		_player.setLooping(false);
		_player.setAudioStreamType(AudioManager.STREAM_MUSIC);
		_player.setDisplay(_holder);
		Log.v("P2PSPlayer", "create player: " + _player.hashCode() + ", playercount=" + _activePlayerCount);
		_player.setOnPreparedListener(new OnPreparedListener() {
			@Override
			public void onPrepared(MediaPlayer arg0) {
				if (arg0 != _player) {
					Log.v("P2PSPlayer", "onPrepared close old player: " + arg0.hashCode());
					try {
						arg0.stop();
					} catch(Exception e) {
						e.printStackTrace();
					}
					try {
						arg0.release();
					} catch(Exception e) {
						e.printStackTrace();
					}
					_activePlayerCount--;
					return;
				}
				Log.v("P2PSPlayer", "onPrepared start current player: " + arg0.hashCode());
				_player.start();
				_preparing = false;
				_seeking = false;
				_everReady = true;
				if (!_onPreparedCalled) {
					_onPreparedCalled = true;
					if (_onPrepared != null) {
						_onPrepared.onPrepared();
					}
				}
				if (_pausing) {
					pause();
				}
				try {
					_timeShift = _dataProvider.inTimeShiftMode() == 1;
				} catch (RemoteException e) {
					e.printStackTrace();
				}
				updateStatusText();
				if (_controllerView != null) {
					((IController)_controllerView).statusChanged();
				}
			}
		});
		_player.setOnErrorListener(new OnErrorListener() {
			@Override
			public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
				if (arg0 != _player) {
					Log.v("P2PSPlayer", "onError release old player: " + arg0.hashCode() + ", playercount=" + _activePlayerCount);
					try {
						arg0.release();
					} catch(Exception e) {
						e.printStackTrace();
					}
					_activePlayerCount--;
					return false;
				}
				if (_dataProvider != null) {
					try {
						if (!_dataProvider.isLive() || _dataProvider.inTimeShiftMode() == 1) {
							_needSeekToOldPos = true;
							_oldPos = _currentPos;
						} else {
							_needSeekToOldPos = false;
						}
					} catch (RemoteException e) {
						e.printStackTrace();
					}
				}
				_preparing = false;
				_everReady = false;
				Log.v("P2PSPlayer", "onError " + arg1 + "," + arg2 + " close current player: " + _player.hashCode() + ", playercount=" + _activePlayerCount);
				closePlayer();
				_handler.sendEmptyMessage(msgRestart);
				return false;
			}

		});
		_player.setOnCompletionListener(new OnCompletionListener() {

			@Override
			public void onCompletion(MediaPlayer arg0) {
				if (arg0 != _player) {
					arg0.release();
					return;
				}
				_preparing = false;
				closePlayer();
				if (_dataProvider != null) {
					try {
						if (_dataProvider.stopped()) {
							return;
						}
					} catch (RemoteException e1) {
						e1.printStackTrace();
					}
					try {
						if (!_dataProvider.isLive() || _dataProvider.inTimeShiftMode() == 1) {
							_needSeekToOldPos = true;
						}
					} catch (RemoteException e) {
						e.printStackTrace();
					}
				}
				_handler.sendEmptyMessage(msgRestart);
			}

		});
		_player.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
			@Override
			public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
				_videoWidth = width;
				_videoHeight = height;
				_updateAspect(-1, -1);
				if (_onVideoSizeChanged != null) {
					_onVideoSizeChanged.onVideoSizeChanged(width, height);
				}
			}
		});
		_player.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {

			@Override
			public void onBufferingUpdate(MediaPlayer mp, int percent) {
				if (_onBufferingUpdate != null) {
					_onBufferingUpdate.onBufferingUpdate(percent);
				}
			}
		});
		int v = android.os.Build.VERSION.SDK_INT;
		if (v < 14) {
			_sf.requestLayout();
		}
		try {
			String url = "http://127.0.0.1:";
			url += Integer.toString(_dataProvider.port());
			if (useTS) {
				if (usePadding) {
					//url += "/live.ts?padding=1";
					url += "/livep.ts";
				} else {
					url += "/live.ts";
				}
			} else {
				url += "/live.m3u8";
			}
			_dataProvider.play();
			Log.v("P2PSPlayer", "Using url: " + url);
			_player.setDataSource(url);
			_player.prepareAsync();
		} catch(Exception e) {
			_preparing = false;
			closePlayer();
			e.printStackTrace();
			return;
		}
		this.setKeepScreenOn(true);

	}

	static private String ToTextN(int l, int n)
	{
		String r = Integer.toString(l);
		while(r.length() < n) {
			r = "0" + r;
		}
		return r;
	}

	static private String ToHHMMSS(int t)
	{
		int s = t / 1000;
		int hh = s / 3600;
		int mm = s / 60 % 60;
		int ss = s % 60;
		return ToTextN(hh,2)+":"+ToTextN(mm,2)+":"+ToTextN(ss,2);
	}

	private void showStatusText()
	{
		_showingStatus = true;
		updateStatusText();
		_handler.removeMessages(msgHideStatus);
		_handler.sendEmptyMessageDelayed(msgHideStatus, 3000);
	}

	///是否在缓冲中
	public boolean isBufferring()
	{
		boolean loading = false;
		if (_seeking) {
			loading = true;
		} else if (playing()) {
			;
		} else if (_pausing) {
			;
		} else if (_ended) {
			;
		} else if (_playing) {
			loading = true;
		}
		if (_usingRaw && _dataProvider != null) {
			try {
				loading = _dataProvider.rawBufferring();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return loading;
	}

	private void updateStatusText()
	{
		String s="";
		boolean loading = false;
		if (_seeking) {
			s = "定位";
			loading = true;
		} else if (playing()) {
			if (isLive()) {
				if (_timeShift) s="回看" ;
				else s = "直播";
			} else if (_ended) {
				s = "结束";
			} else {
				s = "点播";
			}
		} else if (_pausing) {
			s = "暂停";
		} else if (_ended) {
			s = "结束";
		} else if (_playing) {
			s = "加载";
			loading = true;
		}
		if (_usingRaw && _dataProvider != null) {
			try {
				loading = _dataProvider.rawBufferring();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (_lastLoading != loading) {
			_lastLoading = loading;
			if (_controllerView != null) {
				((IController)_controllerView).statusChanged();
			}
		}
		if (_loadingView != null) {
			if (loading) {
				_loadingView.setVisibility(VISIBLE);
			} else {
				_loadingView.setVisibility(INVISIBLE);
			}
		}
		if (!_showingStatus) {
			_statusText.setText("");
			return;
		}
		setTimeText(s);
	}

	private void setTimeText(String s) {
		String lineEnd = "    \n";
		s += lineEnd;
		//if (ready()) {
			if (!isLive()) {
				s += ToHHMMSS(this.currentPosition()) + " / "
						+ ToHHMMSS(this.duration());
				s += lineEnd;
			}
			double tc;
			tc = getTimeCode();
			if (tc != 0) {
				Date d = new Date();
				d.setTime((long)tc);
				s += "时间: ";
				s += _sdf.format(d);
				s += lineEnd;
			}
		//}
		_statusText.setText(s);
	}




	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (_enableDebugKey) {
			if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
				if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
					if (_enableDebugMsg) {
						LayoutParams lp = (LayoutParams)_debugText.getLayoutParams();
						lp.topMargin -= 50;
						_debugText.setLayoutParams(lp);
					}
					if (_debugKeyStateDown) { //要求downKey, 清除状态
						_debugKeyCount = 0;
						_debugKeyStateDown = false;
					} else {
						_debugKeyStateDown = true;
						_debugKeyCount++;
					}
				} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
					if (_enableDebugMsg) {
						LayoutParams lp = (LayoutParams)_debugText.getLayoutParams();
						lp.topMargin += 50;
						_debugText.setLayoutParams(lp);
					}
					if (_debugKeyStateDown) { //要求downKey, 清除状态
						_debugKeyCount++;
						_debugKeyStateDown = false;
					} else {
						_debugKeyStateDown = false;
						_debugKeyCount = 0;
					}
				}
				if (_debugKeyCount > 10) { //触发debugKey
					_debugKeyStateDown = false;
					_debugKeyCount = 0;
					if (_enableDebugMsg) { //已经启用，执行禁用
						enableDebugText(false);
					} else {
						enableDebugText(true);
					}
				}
				_handler.removeMessages(msgInvalidateDebugKey);
				_handler.sendEmptyMessageDelayed(msgInvalidateDebugKey, 2000);

			}
		}
		if (!handleKey) {
			super.onKeyDown(keyCode, event);
			return false;
		}
		if (event.getAction() == KeyEvent.ACTION_DOWN) {
			if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) {
				if (!pausing()) {
					pause();
					showController(true);
				} else {
					resume();
				}
			}
		}
		if (_controllerView != null) {
			return _controllerView.onKeyDown(keyCode, event);
		} else {
			return super.onKeyDown(keyCode, event);
		}
	}

	@Override
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		if (!handleKey) {
			super.onKeyUp(keyCode, event);
			return false;
		}
		if (_controllerView != null) {
			return _controllerView.onKeyUp(keyCode, event);
		} else {
			return super.onKeyUp(keyCode, event);
		}
	}

	static private class AndroidBoxPolicy
	{
		public String name;
		public boolean vodUseTS;
		public boolean liveUseTS;
		public boolean padding;
		public boolean bufferEmptyToEnd;
		public boolean traditionalMode;
		public AndroidBoxPolicy(String aName, boolean aVodUseTS, boolean aLiveUseTS, boolean aPadding, boolean aBufferEmptyToEnd, boolean atraditionalMode)
		{
			name = aName;
			vodUseTS = aVodUseTS;
			liveUseTS = aLiveUseTS;
			padding = aPadding;
			bufferEmptyToEnd = aBufferEmptyToEnd;
			traditionalMode = atraditionalMode;
		}
	}

	//策略表
	private static AndroidBoxPolicy[] gAndroidBoxPolicy = {
		new AndroidBoxPolicy("godbox", true, false, true, false, false),
		new AndroidBoxPolicy("Amlogic", true, true, true, true, true),
		new AndroidBoxPolicy("bigfish", true, true, true, true, false),
		new AndroidBoxPolicy("sun8i", false, false, false, true, true)
	};

	/*!
	 * @brief 自动检测硬件类型，根据策略表获取设置策略
	 * @param live 要播放的视频是否是直播
	 */
	public void setupPlayPolicy(boolean live)
	{
		useTS = false;
		usePadding = true;
		bufferEmptyToEnd = false;
		traditionalMode = false;
		try {
			if (!_hasHardAVC) { //没有h.264硬件解码器接口的我们采用传统模式
				traditionalMode = true;
			}
		} catch(Throwable e) {
			traditionalMode = true;
		}
		String boxType = getBoxType();
		for(int i=0; i<gAndroidBoxPolicy.length; ++i) {
			if (boxType.startsWith(gAndroidBoxPolicy[i].name)) {
				usePadding = gAndroidBoxPolicy[i].padding;
				bufferEmptyToEnd = gAndroidBoxPolicy[i].bufferEmptyToEnd;
				if (gAndroidBoxPolicy[i].traditionalMode)traditionalMode = true;
				if (live) {
					if (gAndroidBoxPolicy[i].liveUseTS) {
						useTS = true;
					} else {
						useTS = false;
					}
				} else {
					if (gAndroidBoxPolicy[i].vodUseTS) {
						useTS = true;
					} else {
						useTS = false;
					}
				}
				return;
			}
		}
	}

	///检测盒子硬件类型, 用于获取设备型号
	public static String getBoxType()
	{
		String cpuInfo = readFileAsString("/proc/cpuinfo");
		int pos = cpuInfo.indexOf("Hardware\t: ");
		if (pos == -1) return "";
		int pos2 = cpuInfo.indexOf("\n", pos);
		if (pos2 == -1) return "";
		return (String)cpuInfo.subSequence(pos+11, pos2);

	}

	///判定是否是机顶盒，目前的判断依据为具有以太网
	public static boolean isTVBox(Context ctx)
	{
		try {
			UiModeManager uiModeManager = (UiModeManager) ctx.getSystemService(ctx.UI_MODE_SERVICE);
			if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) return true;
		} catch(Throwable e) {
			e.printStackTrace();
		}
		try {
			File f = new File("/sys/class/net/eth0");
			return f.exists();
		} catch(Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	///判断是否是使用移动数据网络
	public boolean isExpensiveNetwork()
	{
		 ConnectivityManager cmgr = (ConnectivityManager) this.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
		 try {
			 NetworkInfo ninfo = cmgr.getActiveNetworkInfo();
			 if (ninfo == null) return false;
			 int type = ninfo.getType();
			 if (type != ConnectivityManager.TYPE_ETHERNET && type != ConnectivityManager.TYPE_WIFI) return true;
			 else return false;
		 } catch(Exception e) {
			 e.printStackTrace();
		 }
		 return false;
	}

	private static String readFileAsString(String fileName)

	{

	    String str="";

	    File file=new File(fileName);
	    FileInputStream in=null;

	    try {

	        in =new FileInputStream(file);

	        byte[] buffer=new byte[65536];
	        int r = in.read(buffer);
	        if (r <= 0) return str;
	        str=new String(buffer, 0, r, "UTF-8");

	    } catch (IOException e) {
	    	;

	    } finally {
	    	if (in != null) {
	    		try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
	    	}
	    }
	    return str;
	}

	public String getSupportedVideoCodecList() {
		return _codecList;
	}

   public  void  setPauseViewGone(){
	   if(_pausingView!=null){
		   _pausingView.setVisibility(View.GONE);
		   this.removeView(_pausingView);
	   }

   }

	public  void  setLoadingViewGone(){
		if(_loadingView!=null){
			_loadingView.setVisibility(View.GONE);
			this.removeView(_loadingView);
		}

	}

}
